package com.ib.algokit.forex;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.activequant.core.domainmodel.InstrumentSpecification;
import org.activequant.core.domainmodel.Symbol;
import org.activequant.core.domainmodel.data.QuoteSeries;
import org.activequant.core.types.Currency;
import org.activequant.core.types.OrderSide;
import org.activequant.core.types.SecurityType;

import com.ib.algokit.ForexBracketPositionService.BracketOrderSide;
import com.ib.algokit.InstrumentAnalyzer;
/**
 * Holds the following associated variables:
 * <ul>
 * <li>forexAnalyzers(Map&lt;String,InstrumentAnalyzer&gt;)</li>
 * <li>forexAnalyzersByUnderlying(Map&lt;String,ArrayList&lt;InstrumentAnalyzer&gt;&gt;)</li>
 * <li>forexAnalyzersBySymbol(Map&lt;String,ArrayList&lt;InstrumentAnalyzer&gt;&gt;)</li>
 * <li></li>
 * <li></li>
 * </ul>
 * @author Dimitar
 *
 */
public class CurrencyPairs {	
	/**
	 * private static final Map&lt;String, InstrumentAnalyzer&gt; forexAnalyzers = new ConcurrentHashMap&lt;String, InstrumentAnalyzer&gt;();
	 */
	private static final Map<String, InstrumentAnalyzer> forexAnalyzers = new ConcurrentHashMap<String, InstrumentAnalyzer>();
	/**
	 * private static final Map&lt;String, ArrayList&lt;InstrumentAnalyzer&gt;&gt; forexAnalyzersByUnderlying = new ConcurrentHashMap&lt;String, ArrayList&lt;InstrumentAnalyzer&gt;&gt;();
	 */
	private static final Map<String, ArrayList<InstrumentAnalyzer>> forexAnalyzersByUnderlying = new ConcurrentHashMap<String, ArrayList<InstrumentAnalyzer>>();
	/**
	 * private static final Map&lt;String, ArrayList&lt;InstrumentAnalyzer&gt;&gt; forexAnalyzersBySymbol = new ConcurrentHashMap&lt;String, ArrayList&lt;InstrumentAnalyzer&gt;&gt;();
	 */
	private static final Map<String, ArrayList<InstrumentAnalyzer>> forexAnalyzersBySymbol = new ConcurrentHashMap<String, ArrayList<InstrumentAnalyzer>>();
	/**
	 * private static final Map&lt;String, Integer&gt; longLimitProfitPips = new ConcurrentHashMap&lt;String, Integer&gt;();
	 */
	private static final Map<String, Integer> longLimitProfitPips = new ConcurrentHashMap<String, Integer>();
	/**
	 * private static final Map&lt;String, Integer&gt; shortLimitProfitPips = new ConcurrentHashMap&lt;String, Integer&gt;();
	 */
	private static final Map<String, Integer> shortLimitProfitPips = new ConcurrentHashMap<String, Integer>();
	/**
	 * private static final Map&lt;String, Integer&gt; longStopLossPips = new ConcurrentHashMap&lt;String, Integer&gt;();
	 */
	private static final Map<String, Integer> longStopLossPips = new ConcurrentHashMap<String, Integer>();
	/**
	 * private static final Map&lt;String, Integer&gt; shortStopLossPips = new ConcurrentHashMap&lt;String, Integer&gt;();
	 */
	private static final Map<String, Integer> shortStopLossPips = new ConcurrentHashMap<String, Integer>();
	/**
	 * private static final Map&lt;String, Long&gt; longMaxLimitOrderWaitingMinutes = new ConcurrentHashMap&lt;String, Long&gt;();
	 */
	private static final Map<String, Long> longMaxLimitOrderWaitingMinutes = new ConcurrentHashMap<String, Long>();
	/**
	 * private static final Map&lt;String, Long&gt; shortMaxLimitOrderWaitingMinutes = new ConcurrentHashMap&lt;String, Long&gt;();
	 */
	private static final Map<String, Long> shortMaxLimitOrderWaitingMinutes = new ConcurrentHashMap<String, Long>();
	
	/**
	 * public static double PIP=0.0001;
	 */
	public static double PIP=0.0001;
	
	public static Map<String, InstrumentAnalyzer> getForexAnalyzers(){
		return forexAnalyzers;
	}
	
	public static Map<String, ArrayList<InstrumentAnalyzer>> getForexAnalyzersByUnderlying(){
		return forexAnalyzersByUnderlying;
	}
	
	public static Map<String, ArrayList<InstrumentAnalyzer>> getForexAnalyzersBySymbol(){
		return forexAnalyzersBySymbol;
	}
	
	/**
	 * returns the InstrumentAnalyzer mapped under the given forexPair(String) title (ex. "EUR/USD") from the associated instrumentAnalyzers(Map&lt;String, InstrumentAnalyzer&gt;)
	 * @param forexPair
	 * @return
	 */
	public static InstrumentAnalyzer getForexAnalyzer(String forexPair){
		return forexAnalyzers.get(forexPair);
	}
	/**
	 * returns the ArrayList&lt;InstrumentAnalyzer&gt; mapped under the given symbol(String) from the associated forexAnalyzersBySymbol(Map&lt;String,ArrayList&lt;InstrumentAnalyzer&gt;&gt;)
	 * @param symbol
	 * @return
	 */
	public static List<InstrumentAnalyzer> getForexAnalyzersBySymbol(String symbol){
		return forexAnalyzersBySymbol.get(symbol);
	}
	/**
	 * returns the ArrayList&lt;InstrumentAnalyzer&gt; mapped under the given underlying(String) from the associated forexAnalyzersByUnderlying(Map&lt;String,ArrayList&lt;InstrumentAnalyzer&gt;&gt;)
	 * @param underlying
	 * @return
	 */
	public static List<InstrumentAnalyzer> getForexAnalyzersByUnderlying(String underlying){
		return forexAnalyzersByUnderlying.get(underlying);
	}
	/**
	 * Maps the given FOREX instrumentAnalyzer(InstrumentAnalyzer) into the static associated maps by full name, symbol and underlying for easier access
	 * @param instrumentAnalyzer
	 */
	public static void mapForexAnalyzer(InstrumentAnalyzer instrumentAnalyzer){
		InstrumentSpecification spec = instrumentAnalyzer.getInstrumentSpecification();
		String symbol=spec.getSymbol().toString();
		String currency=spec.getCurrency().toString();
		String fullName=symbol+"/"+currency;
		if(!forexAnalyzers.containsKey(fullName)){
			forexAnalyzers.put(fullName, instrumentAnalyzer);
		}
		ArrayList<InstrumentAnalyzer> forexAnalyzersForSymbol = forexAnalyzersBySymbol.get(symbol);
		if(forexAnalyzersForSymbol==null){
			forexAnalyzersForSymbol = new ArrayList<InstrumentAnalyzer>();
		}
		if(!forexAnalyzersForSymbol.contains(instrumentAnalyzer)){
			forexAnalyzersForSymbol.add(instrumentAnalyzer);
		}
		forexAnalyzersBySymbol.put(symbol, forexAnalyzersForSymbol);
		
		ArrayList<InstrumentAnalyzer> forexAnalyzersForUnderlying = forexAnalyzersByUnderlying.get(currency);
		if(forexAnalyzersForUnderlying==null){
			forexAnalyzersForUnderlying = new ArrayList<InstrumentAnalyzer>();
		}
		if(!forexAnalyzersForUnderlying.contains(instrumentAnalyzer)){
			forexAnalyzersForUnderlying.add(instrumentAnalyzer);
		}
		forexAnalyzersByUnderlying.put(currency, forexAnalyzersForUnderlying);
	}
		
	public static List<InstrumentSpecification> getPairs(){
		List<InstrumentSpecification> currencyPairs = new ArrayList<InstrumentSpecification>();
		//USD
		InstrumentSpecification specGBP_USD=new InstrumentSpecification(new Symbol("GBP"), "SMART", "IB", Currency.USD, SecurityType.CASH);
		specGBP_USD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specGBP_USD);
		InstrumentSpecification specEUR_USD=new InstrumentSpecification(new Symbol("EUR"), "SMART", "IB", Currency.USD, SecurityType.CASH);
		specEUR_USD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specEUR_USD);
//		InstrumentSpecification specCAD_USD=new InstrumentSpecification(new Symbol("CAD"), "SMART", "IB", Currency.USD, SecurityType.CASH);//none
//		specCAD_USD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCAD_USD);
//		InstrumentSpecification specJPY_USD=new InstrumentSpecification(new Symbol("JPY"), "SMART", "IB", Currency.USD, SecurityType.CASH);//none
//		specJPY_USD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specJPY_USD);
//		InstrumentSpecification specCHF_USD=new InstrumentSpecification(new Symbol("CHF"), "SMART", "IB", Currency.USD, SecurityType.CASH);//none
//		specCHF_USD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCHF_USD);
		InstrumentSpecification specNZD_USD=new InstrumentSpecification(new Symbol("NZD"), "SMART", "IB", Currency.USD, SecurityType.CASH);
		specNZD_USD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specNZD_USD);
		InstrumentSpecification specAUD_USD=new InstrumentSpecification(new Symbol("AUD"), "SMART", "IB", Currency.USD, SecurityType.CASH);
		specAUD_USD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specAUD_USD);
		
		//EUR
//		InstrumentSpecification specGBP_EUR=new InstrumentSpecification(new Symbol("GBP"), "SMART", "IB", Currency.EUR, SecurityType.CASH);//none
//		specGBP_EUR.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specGBP_EUR);
//		InstrumentSpecification specUSD_EUR=new InstrumentSpecification(new Symbol("USD"), "SMART", "IB", Currency.EUR, SecurityType.CASH);//none
//		specUSD_EUR.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specUSD_EUR);
//		InstrumentSpecification specCAD_EUR=new InstrumentSpecification(new Symbol("CAD"), "SMART", "IB", Currency.EUR, SecurityType.CASH);//none
//		specCAD_EUR.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCAD_EUR);
//		InstrumentSpecification specJPY_EUR=new InstrumentSpecification(new Symbol("JPY"), "SMART", "IB", Currency.EUR, SecurityType.CASH);//none
//		specJPY_EUR.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specJPY_EUR);
//		InstrumentSpecification specCHF_EUR=new InstrumentSpecification(new Symbol("CHF"), "SMART", "IB", Currency.EUR, SecurityType.CASH);//none
//		specCHF_EUR.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCHF_EUR);
//		InstrumentSpecification specNZD_EUR=new InstrumentSpecification(new Symbol("NZD"), "SMART", "IB", Currency.EUR, SecurityType.CASH);//none
//		specNZD_EUR.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specNZD_EUR);
//		InstrumentSpecification specAUD_EUR=new InstrumentSpecification(new Symbol("AUD"), "SMART", "IB", Currency.EUR, SecurityType.CASH);//none
//		specAUD_EUR.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specAUD_EUR);
		
		//GBP
//		InstrumentSpecification specUSD_GBP=new InstrumentSpecification(new Symbol("USD"), "SMART", "IB", Currency.GBP, SecurityType.CASH);//none
//		specUSD_GBP.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specUSD_GBP);
//		InstrumentSpecification specEUR_GBP=new InstrumentSpecification(new Symbol("EUR"), "SMART", "IB", Currency.GBP, SecurityType.CASH);//none
//		specEUR_GBP.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specEUR_GBP);
//		InstrumentSpecification specCAD_GBP=new InstrumentSpecification(new Symbol("CAD"), "SMART", "IB", Currency.GBP, SecurityType.CASH);//none
//		specCAD_GBP.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCAD_GBP);
//		InstrumentSpecification specJPY_GBP=new InstrumentSpecification(new Symbol("JPY"), "SMART", "IB", Currency.GBP, SecurityType.CASH);//none
//		specJPY_GBP.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specJPY_GBP);
//		InstrumentSpecification specCHF_GBP=new InstrumentSpecification(new Symbol("CHF"), "SMART", "IB", Currency.GBP, SecurityType.CASH);//none
//		specCHF_GBP.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCHF_GBP);
//		InstrumentSpecification specNZD_GBP=new InstrumentSpecification(new Symbol("NZD"), "SMART", "IB", Currency.GBP, SecurityType.CASH);//none
//		specNZD_GBP.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specNZD_GBP);
//		InstrumentSpecification specAUD_GBP=new InstrumentSpecification(new Symbol("AUD"), "SMART", "IB", Currency.GBP, SecurityType.CASH);//none
//		specAUD_GBP.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specAUD_GBP);
		
		//CAD
		InstrumentSpecification specGBP_CAD=new InstrumentSpecification(new Symbol("GBP"), "SMART", "IB", Currency.CAD, SecurityType.CASH);
		specGBP_CAD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specGBP_CAD);
		InstrumentSpecification specEUR_CAD=new InstrumentSpecification(new Symbol("EUR"), "SMART", "IB", Currency.CAD, SecurityType.CASH);
		specEUR_CAD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specEUR_CAD);
		InstrumentSpecification specUSD_CAD=new InstrumentSpecification(new Symbol("USD"), "SMART", "IB", Currency.CAD, SecurityType.CASH);
		specUSD_CAD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specUSD_CAD);
//		InstrumentSpecification specJPY_CAD=new InstrumentSpecification(new Symbol("JPY"), "SMART", "IB", Currency.CAD, SecurityType.CASH);//none
//		specJPY_CAD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specJPY_CAD);
//		InstrumentSpecification specCHF_CAD=new InstrumentSpecification(new Symbol("CHF"), "SMART", "IB", Currency.CAD, SecurityType.CASH);//none
//		specCHF_CAD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCHF_CAD);
//		InstrumentSpecification specNZD_CAD=new InstrumentSpecification(new Symbol("NZD"), "SMART", "IB", Currency.CAD, SecurityType.CASH);//none
//		specNZD_CAD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specNZD_CAD);
		InstrumentSpecification specAUD_CAD=new InstrumentSpecification(new Symbol("AUD"), "SMART", "IB", Currency.CAD, SecurityType.CASH);
		specAUD_CAD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specAUD_CAD);
		
		//JPY
		InstrumentSpecification specGBP_JPY=new InstrumentSpecification(new Symbol("GBP"), "SMART", "IB", Currency.JPY, SecurityType.CASH);
		specGBP_JPY.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specGBP_JPY);
		InstrumentSpecification specEUR_JPY=new InstrumentSpecification(new Symbol("EUR"), "SMART", "IB", Currency.JPY, SecurityType.CASH);
		specEUR_JPY.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specEUR_JPY);
		InstrumentSpecification specCAD_JPY=new InstrumentSpecification(new Symbol("CAD"), "SMART", "IB", Currency.JPY, SecurityType.CASH);
		specCAD_JPY.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specCAD_JPY);
		InstrumentSpecification specUSD_JPY=new InstrumentSpecification(new Symbol("USD"), "SMART", "IB", Currency.JPY, SecurityType.CASH);
		specUSD_JPY.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specUSD_JPY);
		InstrumentSpecification specCHF_JPY=new InstrumentSpecification(new Symbol("CHF"), "SMART", "IB", Currency.JPY, SecurityType.CASH);
		specCHF_JPY.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specCHF_JPY);
		InstrumentSpecification specNZD_JPY=new InstrumentSpecification(new Symbol("NZD"), "SMART", "IB", Currency.JPY, SecurityType.CASH);
		specNZD_JPY.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specNZD_JPY);
		InstrumentSpecification specAUD_JPY=new InstrumentSpecification(new Symbol("AUD"), "SMART", "IB", Currency.JPY, SecurityType.CASH);
		specAUD_JPY.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specAUD_JPY);
		
		//CHF
		InstrumentSpecification specGBP_CHF=new InstrumentSpecification(new Symbol("GBP"), "SMART", "IB", Currency.CHF, SecurityType.CASH);
		specGBP_CHF.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specGBP_CHF);
		InstrumentSpecification specEUR_CHF=new InstrumentSpecification(new Symbol("EUR"), "SMART", "IB", Currency.CHF, SecurityType.CASH);
		specEUR_CHF.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specEUR_CHF);
		InstrumentSpecification specCAD_CHF=new InstrumentSpecification(new Symbol("CAD"), "SMART", "IB", Currency.CHF, SecurityType.CASH);
		specCAD_CHF.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specCAD_CHF);
//		InstrumentSpecification specJPY_CHF=new InstrumentSpecification(new Symbol("JPY"), "SMART", "IB", Currency.CHF, SecurityType.CASH);//none
//		specJPY_CHF.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specJPY_CHF);
		InstrumentSpecification specUSD_CHF=new InstrumentSpecification(new Symbol("USD"), "SMART", "IB", Currency.CHF, SecurityType.CASH);
		specUSD_CHF.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specUSD_CHF);
		InstrumentSpecification specNZD_CHF=new InstrumentSpecification(new Symbol("NZD"), "SMART", "IB", Currency.CHF, SecurityType.CASH);
		specNZD_CHF.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specNZD_CHF);
		InstrumentSpecification specAUD_CHF=new InstrumentSpecification(new Symbol("AUD"), "SMART", "IB", Currency.CHF, SecurityType.CASH);
		specAUD_CHF.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specAUD_CHF);
		
		//NZD
		InstrumentSpecification specGBP_NZD=new InstrumentSpecification(new Symbol("GBP"), "SMART", "IB", Currency.NZD, SecurityType.CASH);
		specGBP_NZD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specGBP_NZD);
		InstrumentSpecification specEUR_NZD=new InstrumentSpecification(new Symbol("EUR"), "SMART", "IB", Currency.NZD, SecurityType.CASH);
		specEUR_NZD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specEUR_NZD);
		
		
		//tested till here		
//		InstrumentSpecification specCAD_NZD=new InstrumentSpecification(new Symbol("CAD"), "SMART", "IB", Currency.NZD, SecurityType.CASH);//none
//		specCAD_NZD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCAD_NZD);
//		InstrumentSpecification specJPY_NZD=new InstrumentSpecification(new Symbol("JPY"), "SMART", "IB", Currency.NZD, SecurityType.CASH);//none
//		specJPY_NZD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specJPY_NZD);
//		InstrumentSpecification specUSD_NZD=new InstrumentSpecification(new Symbol("USD"), "SMART", "IB", Currency.NZD, SecurityType.CASH);//none
//		specUSD_NZD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specUSD_NZD);
//		InstrumentSpecification specCHF_NZD=new InstrumentSpecification(new Symbol("CHF"), "SMART", "IB", Currency.NZD, SecurityType.CASH);//none
//		specCHF_NZD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCHF_NZD);
		InstrumentSpecification specAUD_NZD=new InstrumentSpecification(new Symbol("AUD"), "SMART", "IB", Currency.NZD, SecurityType.CASH);
		specAUD_NZD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specAUD_NZD);
		
		//AUD
		InstrumentSpecification specGBP_AUD=new InstrumentSpecification(new Symbol("GBP"), "SMART", "IB", Currency.AUD, SecurityType.CASH);
		specGBP_AUD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specGBP_AUD);
		InstrumentSpecification specEUR_AUD=new InstrumentSpecification(new Symbol("EUR"), "SMART", "IB", Currency.AUD, SecurityType.CASH);
		specEUR_AUD.setPrimaryExchange("IDEALPRO");
		currencyPairs.add(specEUR_AUD);
//		InstrumentSpecification specCAD_AUD=new InstrumentSpecification(new Symbol("CAD"), "SMART", "IB", Currency.AUD, SecurityType.CASH);//none
//		specCAD_AUD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCAD_AUD);
//		InstrumentSpecification specJPY_AUD=new InstrumentSpecification(new Symbol("JPY"), "SMART", "IB", Currency.AUD, SecurityType.CASH);//none
//		specJPY_AUD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specJPY_AUD);
//		InstrumentSpecification specCHF_AUD=new InstrumentSpecification(new Symbol("CHF"), "SMART", "IB", Currency.AUD, SecurityType.CASH);//none
//		specCHF_AUD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specCHF_AUD);
//		InstrumentSpecification specNZD_AUD=new InstrumentSpecification(new Symbol("NZD"), "SMART", "IB", Currency.AUD, SecurityType.CASH);//none
//		specNZD_AUD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specNZD_AUD);
//		InstrumentSpecification specUSD_AUD=new InstrumentSpecification(new Symbol("USD"), "SMART", "IB", Currency.AUD, SecurityType.CASH);//none
//		specUSD_AUD.setPrimaryExchange("IDEALPRO");
//		currencyPairs.add(specUSD_AUD);
		
		return currencyPairs;
	}
	
	/**
	 * converts the given fromAmount(double) from the given fromCurrency(Currency) to the given toCurrency(Currency)
	 * @param fromCurrency
	 * @param fromAmount
	 * @param toCurrency
	 * @return
	 */
	public static double convert(Currency fromCurrency, double fromAmount, Currency toCurrency){
		String pair=fromCurrency.toString()+"/"+toCurrency.toString();
		InstrumentAnalyzer analyzer = CurrencyPairs.getForexAnalyzer(pair);
		double toAmount=0;
		if(analyzer!=null){
			double bidPrice=analyzer.getLiveQuoteSeriesBag().get().get(0).getBidPrice();
			toAmount=bidPrice*fromAmount;			
		}else{
			pair=toCurrency.toString()+"/"+fromCurrency.toString();
			analyzer = CurrencyPairs.getForexAnalyzer(pair);
			double askPrice=analyzer.getLiveQuoteSeriesBag().get().get(0).getAskPrice();
			toAmount=fromAmount/askPrice;
		}
		return toAmount;
	}
	/**
	 * converts the given USDAmount(double) from USD to the given toCurrency(Currency)
	 * @param fromCurrency
	 * @param fromAmount
	 * @param toCurrency
	 * @return
	 */
	public static double convertFromUSDFixedRate(double USDAmount, Currency toCurrency){	
		double toAmount=0;
		switch(toCurrency) {
		case USD: 
			toAmount=USDAmount;
			break;
		case GBP:
			toAmount=0.6167*USDAmount;
//			toAmount=0.6118*USDAmount;//usd/gbp
			break;
		case EUR: 
			toAmount=0.7035*USDAmount;
//			toAmount=0.6930*USDAmount;
			break;
		case CHF: 
			toAmount=0.7633*USDAmount;
//			toAmount=0.9064*USDAmount;
			break;
		case AUD: 
			toAmount= 0.9705*USDAmount;
//			toAmount=0.9525*USDAmount;
			break;
		case CAD: 
			toAmount=0.9865*USDAmount;
//			toAmount=0.9567*USDAmount;
			break;
		case NZD:
			toAmount=1.2060*USDAmount;
//			toAmount=1.2842*USDAmount;
			break;
		case JPY:
			toAmount=76.8700*USDAmount;
//			toAmount=84.6600*USDAmount;
			break;
		default:
			throw new IllegalArgumentException("round up not supported/implemented: " + toCurrency);
		}            
		return toAmount;
	}
	
	public static double convertFromUSDLastKnownRealTimeRate(double USDAmount, Currency toCurrency){
		double toAmount=0;
		InstrumentAnalyzer analyzer=null;
		switch(toCurrency) {
		case USD: 
			toAmount=USDAmount;
			break;
		case GBP:
			analyzer=getForexAnalyzers().get("GBP/USD");
			if(analyzer!=null){
				QuoteSeries quoteSeries= analyzer.getLiveQuoteSeriesBag().get();
				if(quoteSeries!=null&&quoteSeries.size()!=0){
					double divisor=quoteSeries.get(0).getAskPrice();
					if(divisor>0){
						toAmount=USDAmount/divisor;
					}
				}
			}
//			toAmount=0.6167*USDAmount;
//			toAmount=0.6118*USDAmount;//usd/gbp
			break;
		case EUR:
			analyzer=getForexAnalyzers().get("EUR/USD");
			if(analyzer!=null){
				QuoteSeries quoteSeries= analyzer.getLiveQuoteSeriesBag().get();
				if(quoteSeries!=null&&quoteSeries.size()!=0){
					double divisor=quoteSeries.get(0).getAskPrice();
					if(divisor>0){
						toAmount=USDAmount/divisor;
					}
				}
			}
//			toAmount=0.7035*USDAmount;
//			toAmount=0.6930*USDAmount;
			break;
		case CHF:
			analyzer=getForexAnalyzers().get("USD/CHF");
			if(analyzer!=null){
				QuoteSeries quoteSeries= analyzer.getLiveQuoteSeriesBag().get();
				if(quoteSeries!=null&&quoteSeries.size()!=0){
					double multiplier=quoteSeries.get(0).getAskPrice();
					if(multiplier>0){
						toAmount=USDAmount*multiplier;
					}
				}
			}
//			toAmount=0.7633*USDAmount;
//			toAmount=0.9064*USDAmount;
			break;
		case AUD: 
			analyzer=getForexAnalyzers().get("AUD/USD");
			if(analyzer!=null){
				QuoteSeries quoteSeries= analyzer.getLiveQuoteSeriesBag().get();
				if(quoteSeries!=null&&quoteSeries.size()!=0){
					double divisor=quoteSeries.get(0).getAskPrice();
					if(divisor>0){
						toAmount=USDAmount/divisor;
					}
				}
			}
//			toAmount= 0.9705*USDAmount;
//			toAmount=0.9525*USDAmount;
			break;
		case CAD:
			analyzer=getForexAnalyzers().get("USD/CAD");
			if(analyzer!=null){
				QuoteSeries quoteSeries= analyzer.getLiveQuoteSeriesBag().get();
				if(quoteSeries!=null&&quoteSeries.size()!=0){
					double multiplier=quoteSeries.get(0).getAskPrice();
					if(multiplier>0){
						toAmount=USDAmount*multiplier;
					}
				}
			}
//			toAmount=0.9865*USDAmount;
//			toAmount=0.9567*USDAmount;
			break;
		case NZD:
			analyzer=getForexAnalyzers().get("NZD/USD");
			if(analyzer!=null){
				QuoteSeries quoteSeries= analyzer.getLiveQuoteSeriesBag().get();
				if(quoteSeries!=null&&quoteSeries.size()!=0){
					double divisor=quoteSeries.get(0).getAskPrice();
					if(divisor>0){
						toAmount=USDAmount/divisor;
					}
				}
			}
//			toAmount=1.2060*USDAmount;
//			toAmount=1.2842*USDAmount;
			break;
		case JPY:
			analyzer=getForexAnalyzers().get("USD/JPY");
			if(analyzer!=null){
				QuoteSeries quoteSeries= analyzer.getLiveQuoteSeriesBag().get();
				if(quoteSeries!=null&&quoteSeries.size()!=0){
					double multiplier=quoteSeries.get(0).getAskPrice();
					if(multiplier>0){
						toAmount=USDAmount*multiplier;
					}
				}
			}
//			toAmount=76.8700*USDAmount;
//			toAmount=84.6600*USDAmount;
			break;
		default:
			throw new IllegalArgumentException("round up not supported/implemented: " + toCurrency);
		}            
		return toAmount;
		
	}
	/**
	 * rounds the given price(double) Up or Down so it has the right number of decimals for setting in the order
	 * @param baseCurrency
	 * @param quoteCurrency
	 * @param price
	 * @param roundMode
	 * @return
	 */
	public static double roundCurrencyPrice(Currency baseCurrency, Currency quoteCurrency, double price, int roundMode){		
		double roundedPrice=0;
		switch(quoteCurrency) {
			case USD: case CAD: case GBP: case AUD:		
				roundedPrice=customIBRounding(price, 5, roundMode);
				break;			
			case CHF:				
				switch(baseCurrency) {
					case USD: case JPY: case AUD: case CAD: case EUR: case GBP:
						roundedPrice=customIBRounding(price, 5, roundMode);
						break;
					case NZD:
						BigDecimal bd = new BigDecimal(Double.toString(price));
						bd = bd.setScale(4, roundMode);
						roundedPrice=bd.doubleValue();
						break;						
					default:
				}				
				break;
			case NZD:				
				switch(baseCurrency) {
					case AUD:
						roundedPrice=customIBRounding(price, 5, roundMode);
						break;
					 case EUR: case GBP:						 
						 BigDecimal bd = new BigDecimal(Double.toString(price));
						 bd = bd.setScale(4, roundMode);
						 roundedPrice=bd.doubleValue();
						break;						
					default:
				}				
				break;	
			case EUR:				
				switch(baseCurrency) {
					case USD: case JPY: case CHF: case AUD: case CAD: case NZD: case EUR:
						BigDecimal bd = new BigDecimal(Double.toString(price));
						bd = bd.setScale(5, roundMode);
						roundedPrice=bd.doubleValue();
						break;
					case GBP:
						bd = new BigDecimal(Double.toString(price));
						bd = bd.setScale(4, roundMode);
						roundedPrice=bd.doubleValue();
						break;						
					default:
				}				
				break;
			case JPY:
				switch(baseCurrency) {
					case USD: case JPY: case CHF: case AUD: case CAD: case GBP: case EUR:
						roundedPrice=customIBRounding(price, 3, roundMode);
						break;
					case NZD:
						BigDecimal bd = new BigDecimal(Double.toString(price));
						bd = bd.setScale(2, roundMode);
						roundedPrice=bd.doubleValue();
						break;						
					default:						
				}
				break;
			default:
		}	
		return roundedPrice;
	}
	
	public static double roundUpAmount(Currency currency, double amount){
		int roundedUpAmount=0;
		switch(currency) {
		  case USD: case GBP: case EUR: case CHF: case AUD: case CAD: case NZD:
			roundedUpAmount=(int)(amount/10000)*10000;
			if(roundedUpAmount<amount){
				roundedUpAmount=roundedUpAmount+10000;
			}
			break;
		  case JPY:
			roundedUpAmount=(int)(amount/100000)*100000;
			if(roundedUpAmount<amount){
				roundedUpAmount=roundedUpAmount+100000;
			}
			break;
		  default:
			throw new IllegalArgumentException("round up not supported/implemented: " + currency);
		}
		return roundedUpAmount;
	}
	/**
	 * this rounds the given price with the given scale and then the last digit is either cut of or turned into a 5 (if between 3 and 7)
	 * @param price
	 * @param scale
	 * @param roundingMode
	 * @return
	 */
	public static double customIBRounding(double price, int scale, int roundingMode){
		BigDecimal bd = new BigDecimal(Double.toString(price));
		bd = bd.setScale(scale, roundingMode);
		double roundedPrice=bd.doubleValue();
		String priceString= Double.toString(roundedPrice);
		String fractionalPartString="";
		int decPointIndex=priceString.lastIndexOf(".");
		if(decPointIndex!=-1){
			fractionalPartString=priceString.substring(decPointIndex+1);
		}
		int numberOfFractionalDigits = fractionalPartString.length();
		if(numberOfFractionalDigits==scale){
			int lastDigit=Integer.parseInt(priceString.substring(priceString.length()-1));
			if(lastDigit<3||lastDigit>7){
				bd = bd.setScale(numberOfFractionalDigits-1, roundingMode);
			}else{
				priceString=priceString.substring(0,priceString.length()-1)+"5";
				bd = new BigDecimal(priceString);				
			}
		}
		return bd.doubleValue();
	}
	/**
	 * returns the given price(double) rounded to the given scale(int) using the given roundingMode(int)
	 * @param price
	 * @param scale
	 * @param roundingMode
	 * @return
	 */
	public static double simpleRounding(double price, int scale, int roundingMode){
		BigDecimal bd = new BigDecimal(Double.toString(price));
		bd = bd.setScale(scale, roundingMode);
		double roundedPrice=bd.doubleValue();
		return roundedPrice;
	}
	/**
	 * returns the bracket order profit/loss pips for the given base/quote currency pair
	 * @param baseCurrency
	 * @param quoteCurrency
	 * @param bracketOrderSide
	 * @return
	 */
	public static Integer getBracketPipsForPair(Currency baseCurrency, Currency quoteCurrency, BracketOrderSide bracketOrderSide, OrderSide orderSide){
		String pair=baseCurrency.toString()+"/"+quoteCurrency.toString();
		boolean isLong=orderSide==OrderSide.BUY;
		boolean isLimitProfit=bracketOrderSide==BracketOrderSide.LIMITPROFIT;
		Integer pips= isLong?(isLimitProfit?longLimitProfitPips.get(pair):longStopLossPips.get(pair)) : (isLimitProfit?shortLimitProfitPips.get(pair):shortStopLossPips.get(pair));
		if(pips!=null){
			return pips;
		}
//		if(isLong){
//			if(isLimitProfit){
//				int longLimitProfitPips=GenomeProperties.getInstance().getPropertyInt(pair+"."+GenomeProperties.LONG_LIMIT_PROFIT_PIPS,0);	
//				if(longLimitProfitPips!=0){
//					pips=longLimitProfitPips;
//				}
//			}else{
//				int longStopLossPips=GenomeProperties.getInstance().getPropertyInt(pair+"."+GenomeProperties.LONG_STOP_LOSS_PIPS,0);	
//				if(longStopLossPips!=0){
//					pips=longStopLossPips;
//				}
//			}
//		}else{
//			if(isLimitProfit){
//				int shortLimitProfitPips=GenomeProperties.getInstance().getPropertyInt(pair+"."+GenomeProperties.SHORT_LIMIT_PROFIT_PIPS,0);
//				if(shortLimitProfitPips!=0){
//					pips=shortLimitProfitPips;
//				}
//			}else{
//				int shortStopLossPips=GenomeProperties.getInstance().getPropertyInt(pair+"."+GenomeProperties.SHORT_STOP_LOSS_PIPS,0);
//				if(shortStopLossPips!=0){
//					pips=shortStopLossPips;
//				}
//			}			
//		}
		if(pips==null){
			switch(quoteCurrency) {
				case USD: case CAD: case GBP: case AUD:		
					pips=bracketOrderSide==BracketOrderSide.LIMITPROFIT?10:10;
					break;			
				case CHF:				
					switch(baseCurrency) {
						case USD: case JPY: case AUD: case CAD: case EUR: case GBP:
							pips=isLimitProfit?10:10;
							break;
						case NZD:
							pips=isLimitProfit?10:10;
							break;						
						default:
					}				
					break;
				case NZD:				
					switch(baseCurrency) {
						case AUD:
							pips=isLimitProfit?10:10;
							break;
						 case EUR: case GBP:						 
							 pips=isLimitProfit?10:10;
							break;						
						default:
					}				
					break;	
				case EUR:				
					switch(baseCurrency) {
						case USD: case JPY: case CHF: case AUD: case CAD: case NZD: case EUR:
							pips=isLimitProfit?10:10;
							break;
						case GBP:
							pips=isLimitProfit?10:10;
							break;						
						default:
					}				
					break;
				case JPY:
					switch(baseCurrency) {
						case USD: case JPY: case CHF: case AUD: case CAD: case GBP: case EUR:
							pips=isLimitProfit?10:10;
							break;
						case NZD:
							pips=isLimitProfit?10:10;
							break;						
						default:						
					}
					break;
				default:
			}
		}
//		if(RunMe.numberOfBackTestLoops>1){
//			pips = 10;
//		}
		if(isLong){
			if(isLimitProfit){
				longLimitProfitPips.put(pair,pips);
			}else{
				longStopLossPips.put(pair,pips);
			}
		}else{
			if(isLimitProfit){
				shortLimitProfitPips.put(pair,pips);
			}else{
				shortStopLossPips.put(pair,pips);
			}
		}
		return pips;
	}
	/**
	 * resets all longMaxLimitOrderWaitingMinutes and shortMaxLimitOrderWaitingMinutes values with the given minutes(long) 
	 * @param minutes
	 */
	public static void setAllPairsMaxLimitOrderWaitingMinutes(Long minutes){
		longMaxLimitOrderWaitingMinutes.clear();
		shortMaxLimitOrderWaitingMinutes.clear();
		List<InstrumentSpecification> specs= getPairs();
		for(InstrumentSpecification spec:specs){
			String pair=spec.getSymbol().toString()+"/"+spec.getCurrency().toString();
			longMaxLimitOrderWaitingMinutes.put(pair, minutes);
			shortMaxLimitOrderWaitingMinutes.put(pair, minutes);
		}
	}
	
	public static void setMaxLimitOrderWaitingMinutes(String pair, Long minutes, OrderSide orderSide){
		boolean isLong=orderSide==OrderSide.BUY;
		if(isLong){
			longMaxLimitOrderWaitingMinutes.put(pair, minutes);
		}else{
			shortMaxLimitOrderWaitingMinutes.put(pair, minutes);
		}
		
	}
	
	public static void setMaxLimitOrderWaitingMinutes(Currency baseCurrency, Currency quoteCurrency, Long minutes, OrderSide orderSide){
		String pair=baseCurrency.toString()+"/"+quoteCurrency.toString();
		boolean isLong=orderSide==OrderSide.BUY;
		if(isLong){
			longMaxLimitOrderWaitingMinutes.put(pair, minutes);
		}else{
			shortMaxLimitOrderWaitingMinutes.put(pair, minutes);
		}
	}
	
	public static Long getMaxLimitOrderWaitingMinutes(String pair, OrderSide orderSide){
		boolean isLong=orderSide==OrderSide.BUY;
		boolean notThereYet = isLong? (longMaxLimitOrderWaitingMinutes==null||!longMaxLimitOrderWaitingMinutes.containsKey(pair)) : (shortMaxLimitOrderWaitingMinutes==null||!shortMaxLimitOrderWaitingMinutes.containsKey(pair)) ;
		if(notThereYet){
			String baseCur=pair.substring(0,3);
			String quoteCur=pair.substring(4);
			Currency baseCurrency=Currency.toClass(baseCur);
			Currency quoteCurrency= Currency.toClass(quoteCur);
			return getMaxLimitOrderWaitingMinutes(baseCurrency, quoteCurrency, orderSide);
		}
		Long minutes=isLong?longMaxLimitOrderWaitingMinutes.get(pair) : shortMaxLimitOrderWaitingMinutes.get(pair);
		return minutes;
	}
	
	public static Long getMaxLimitOrderWaitingMinutes(Currency baseCurrency, Currency quoteCurrency, OrderSide orderSide){
		boolean isLong=orderSide==OrderSide.BUY;
		String pair=baseCurrency.toString()+"/"+quoteCurrency.toString();
		Long minutes=isLong?longMaxLimitOrderWaitingMinutes.get(pair):shortMaxLimitOrderWaitingMinutes.get(pair);
		if(minutes!=null){
			return minutes;
		}		
		
		if(minutes==null){
			switch(quoteCurrency) {
				case USD: 
					switch(baseCurrency) {
						case JPY: case CAD:
							minutes=15L;
							break;
						case NZD:
							minutes=15L;
							break;
						case AUD:
							minutes=15L;
							break;
						case CHF:
							minutes=15L;
							break;	
						case EUR:
							minutes=15L;
							break;	
						case GBP:
							minutes=15L;
							break;	
						default:
					}				
					break;
				case CAD: 
					switch(baseCurrency) {
						case JPY:
							minutes=15L;
							break;
						case USD:
							minutes=15L;
							break;	
						case NZD:
							minutes=15L;
							break;
						case AUD:
							minutes=15L;
							break;
						case CHF:
							minutes=15L;
							break;	
						case EUR:
							minutes=15L;
							break;	
						case GBP:
							minutes=15L;
							break;	
						default:
					}				
					break;
				case GBP: case AUD:		
					minutes=15L;
					break;			
				case CHF:				
					switch(baseCurrency) {
						case JPY: case CAD:
							minutes=15L;
							break;
						case NZD:
							minutes=15L;
							break;
						case AUD:
							minutes=15L;
							break;
						case USD:
							minutes=15L;
							break;	
						case GBP:
							minutes=15L;
							break;
						case EUR:
							minutes=15L;
							break;	
						default:
					}				
					break;
				case NZD:				
					switch(baseCurrency) {
						case AUD:
							minutes=15L;
							break;
						case GBP:	
							minutes=15L;
							break;	
						case EUR:					 
							minutes=15L;
							break;						
						default:
					}				
					break;	
				case EUR:				
					switch(baseCurrency) {
						case USD: case JPY: case CHF: case AUD: case CAD: case NZD:
							minutes=15L;
							break;
						case GBP:
							minutes=15L;
							break;						
						default:
					}				
					break;
				case JPY:
					switch(baseCurrency) {
						case EUR:
							minutes=15L;
							break;	
						case CHF:
							minutes=15L;
							break;	
						case USD:
							minutes=15L;
							break;	
						case AUD: case CAD: case GBP:
							minutes=15L;
							break;
						case NZD:
							minutes=15L;
							break;						
						default:						
					}
					break;
				default:
			}
		}
//		if(RunMe.numberOfBackTestLoops>1){
//			minutes = 15L;
//		}
		if(isLong){
			longMaxLimitOrderWaitingMinutes.put(pair,minutes);
		}else{
			shortMaxLimitOrderWaitingMinutes.put(pair,minutes);
		}
		
		return minutes;
	}

}
